﻿@page "/DialogService"

<PageTitle>@App.PageTitle("DialogService")</PageTitle>

<h1>DialogService</h1>

<p>
    The DialogService is a service that can be used to show dialogs. It can be injected into a page or component and is used to show
    different type of dialogs.
</p>
<p>
    For a component to be useable by the DialogService, it needs to implement <code>IDialogContentComponent&lt;T&gt;</code>.
</p>
<p>
    The DialogService is automatically registered in the DI container with the <code>.AddFluentUIComponents()</code> method call.
</p>

<h2>Dialog provider</h2>
<p>
    Dialogs are rendered by the <code>&lt;FluentDialogProvider /&gt;</code>. This component needs to be added to the main layout of your application/site.
    You typically do this in the <code>MainLayout.razor</code> file at the end of the <code>&lt;main&gt;</code> section like this:
</p>
<CodeSnippet Language="razor">
    @(
@"<main>
    <nav>
        <!-- -->
    </nav>
    <div class=""content"">
        <article id=""article"">
            @Body
        </article>
    </div>
    <FluentDialogProvider />
</main>"
    )
</CodeSnippet>
<blockquote>
    <p><strong>IMPORTANT!!</strong></p>
    <p>
        For the <code>&lt;FluentDialogProvider/&gt;</code> to work properly, it needs interactivity! If you are using "per page" interactivity or <strong>Server Side Rendering</strong>
        (ASP.NET Core 8 or above), make sure to add a <code>@@rendermode</code> to either the provider itself or the component the provider is placed in.
    </p>
</blockquote>
<p>
    See the following pages for examples on how to use the DialogService with the different types of dialogs.
    <ul>
        <li><a href="/Dialog">Regular dialogs</a></li>
        <li><a href="/MessageBox">Message boxes</a></li>
        <li><a href="/Panel">Panels</a></li>
        <li><a href="/SplashScreen">Splash screens</a></li>
    </ul>
</p>

<h2>Exchange data between dialog and calling component</h2>
<p>
    There are two ways to exchange data between the dialog and the component which calls the dialog. The first is by capturing the returned <code>IDialogReference</code> from one of the <code>DialogService.Show...Async</code> methods and then use that
    reference to get the dialog's result (of type <code>DialogResult</code>). The second is by using an <code>EventCalback</code> parameter as part of the
    <code>DialogParameters</code>.
</p>
<h3>Using async/await with an <code>IDialogReference</code></h3>
<p>
    You can use the <code>DialogService.Show...Async()</code> methods to show a dialog. When the type of dialog supports data exchange with the
    callingcomponent, these methods return an <code>IDialogReference</code> which can be used to get the dialog's result. The
    <code>DialogResult</code> contains the data that was passed to and altered in the dialog. It also contains a <code>Cancelled</code> property
    which indicates if the dialog was cancelled or not.
</p>
<p>
    A typical implementation could look something like this:
    <CodeSnippet Language="csharp">
        @(
@"DialogParameters<SimplePerson> parameters = new()
{
    Title = $""Hello {simplePerson.Firstname}"",
    PrimaryAction = ""Yes"",
    PrimaryActionEnabled = false,
    SecondaryAction = ""No"",
    Width = ""500px"",
    Height = ""500px"",
    Content = simplePerson,
    TrapFocus = _trapFocus,
    Modal = _modal,
};

IDialogReference dialog = await DialogService.ShowDialogAsync<SimpleDialog, SimplePerson>(parameters);
DialogResult? result = await dialog.Result;

if (result.Data is not null)
{
    SimplePerson? simplePerson = result.Data as SimplePerson;
    Console.WriteLine($""Dialog closed by {simplePerson?.Firstname} {simplePerson?.Lastname} ({simplePerson?.Age}) - Canceled: {result.Cancelled}"");
}
else
{
    Console.WriteLine($""[DialogService] Dialog closed - Canceled: {result.Cancelled}"");
}"
        )
    </CodeSnippet>
</p>

<h3>Using an EventCallback</h3>
<p>
    You can exchange data between the component that opened the dialog and the dialog component by using the <code>DialogParameters.Content</code>
    parameter to specify the type of data and providing a callback function to the <code>DialogParameters.OnDialogResult</code> method. <br />
    Any changes you make to the data in the Dialog component will be reflected in the Data object in the calling component when the dialog is closed.<br />
    You can use the <code>CreateDialogCallback</code> method in the <code>Dialogservice</code> to create the callback function.<br />
    Typically a call would look like this:
    <CodeSnippet Language="csharp">OnDialogResult = DialogService.CreateDialogCallback(this, HandleIt),</CodeSnippet>
    where <code>this</code> represents the dialog calling component and <code>HandleIt</code> is the method in the calling component that will be called
    when the dialog is closed. It receives the <code>DialogResult</code> as a parameter.
</p>

<p>
    An typical implemtation could look something like this:
    <CodeSnippet Language="csharp">
        @(
@"private async Task HandleIt(DialogResult result)
{
    if (result.Cancelled)
    {
        //Handle the cancellation
        return;
    }
    if (result.Data is not null)
    {
        //Handle the data
    }
    //Handle closing the dialog
    await Task.Run(() => ...);
}"
        )
    </CodeSnippet>
</p>

<ApiDocumentation Component="typeof(DialogService)" />
<ApiDocumentation Component="typeof(FluentDialogProvider)" />
